package com.hoongs.v1.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hoongs.v1.dto.OrderPageDto;
import com.hoongs.v1.entity.*;
import com.hoongs.v1.mapper.*;
import com.hoongs.v1.server.WebSocketServer;
import com.hoongs.v1.service.OrderService;
import com.hoongs.v1.utils.DateUtil;
import com.hoongs.v1.utils.PResult;
import com.hoongs.v1.utils.Result;
import com.hoongs.v1.utils.SnowFlake;
import com.hoongs.v1.vo.OrderVo;
import com.hoongs.v1.vo.ProductVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.hoongs.v1.utils.DateUtil.getTodayTnterval;

@Service
public class OrderServiceImpl implements OrderService {

    public static final String NOT_FOUND_ARTICLE = "没有找到该订单！";

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private OrderProductMapper orderProductMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private CartMapper cartMapper;

    @Resource
    private ProductMapper productMapper;

    @Resource
    private AddressMapper addressMapper;

    @Resource
    private RiderMapper riderMapper;

    @Resource
    private DictMapper dictMapper;

    @Resource
    private SettingsMapper settingsMapper;

    @Resource
    WebSocketServer webSocketServer;

//    @Resource
//    private WebSocketServer webSocketServer = new WebSocketServer();


    /**
     * 根据用户查询所有订单数据
     *
     * @param token
     * @return
     */
    @Override
    public Result selectListByUser(String token) {
        User user = UserServiceImpl.getUserInfoByToken(token, userMapper);
        if (user == null) return Result.opError("请先登录！");
        // 查询用户所有订单列表
        List<Order> orderList = orderMapper.selectList(new QueryWrapper<Order>().eq("user_id", user.getId()).orderByDesc("create_time"));
        // 查询用户所有订单商品
        List<OrderProduct> orderProductList = orderProductMapper.selectList(new QueryWrapper<OrderProduct>().eq("user_id", user.getId()));

        List<ProductVo> productVoList = new ArrayList<>();
        // 根据订单商品查询出商品的详细信息
        for (OrderProduct op : orderProductList) {
            Product product = productMapper.selectById(op.getProductId());
            if (product != null) {
                productVoList.add(ProductVo.voFromOPDao(product, op));
            }
        }

        ArrayList<OrderVo> results = new ArrayList<>();
        for (Order orderItem : orderList) {
            OrderVo orderVo = OrderVo.voFromDao(orderItem);
            List<ProductVo> productVos = productVoList.stream().filter((item -> item.getOrderId().equals(orderItem.getId()))).collect(Collectors.toList());
            orderVo.setProductList((ArrayList<ProductVo>) productVos);
            results.add(orderVo);
        }
        return Result.success(results);
    }

    @Override
    @Transactional
    public Result addByUser(OrderVo orderVo, String token) {
        // 检查用户权限
        User user = UserServiceImpl.getUserInfoByToken(token, userMapper);
        if (user == null) return Result.opError("请先登录！");

        // 检查是否营业中
        Settings settings = settingsMapper.selectOne(new QueryWrapper<Settings>().eq("prop", "isBusiness"));
        if ("0".equals(settings.getValue())) return Result.opError("对不起，店铺不在营业中！");

        // 获取今天的订单数量
        List<String> times = getTodayTnterval();
        Long ordernum = orderMapper.selectCount(new QueryWrapper<Order>().between("create_time", times.get(0), times.get(1)));


        // 雪花算法生成订单code
        SnowFlake snowFlake = new SnowFlake(3, 3);

        // 拼装订单数据
        Order order = OrderVo.voToDao(orderVo);
        String ordercode = String.valueOf(snowFlake.nextId());
        order.setUserId(user.getId());
        order.setUserName(user.getUsername());
        order.setOrderCode(ordercode);
        order.setOrderNum(BigDecimal.valueOf(ordernum + 1));
        order.setStatus("1");
        order.setIspaid("0");
        order.setTotalAmount(new BigDecimal(0));
        order.setTotalNum(new BigDecimal(0));
        order.setOrderTime(LocalDateTime.now());

        // 如果订单生成失败直接返回
        if (orderMapper.insert(order) != 1) return Result.opError();

        // 遍历用户的购物车数据，将购物车商品转为订单商品，并且计算总价格和总数量
        List<Cart> cartList = cartMapper.selectList(new QueryWrapper<Cart>().eq("user_id", user.getId()));
        BigDecimal totalAmount = new BigDecimal(0);
        BigDecimal totalNum = new BigDecimal(0);
        for (Cart cart : cartList) {
            OrderProduct orderProduct = OrderProduct.fromCart(cart, order);
            orderProduct.setPrice(productMapper.selectById(orderProduct.getProductId()).getPrice());
            if (orderProductMapper.insert(orderProduct) == 1) {
                cartMapper.deleteById(cart.getId());
                totalAmount = totalAmount.add(orderProduct.getNumber().multiply(orderProduct.getPrice()));
                totalNum = totalNum.add(orderProduct.getNumber());
            }
        }
        order.setTotalAmount(totalAmount);
        order.setTotalNum(totalNum);

        // 订单需要配送，分配骑手
        if ("2".equals(order.getSendmode())) {
            Rider rider = findNextRider();
            if (rider != null) {
                order.setRiderId(rider.getId());
                order.setRiderName(rider.getName());
                order.setRiderMobile(rider.getMobile());
                // 通知骑手有新订单
                SocketMsg socketMsg = new SocketMsg();
                socketMsg.setType("1");
                socketMsg.setActionType("88");
                socketMsg.setToId(rider.getUserId());
                socketMsg.setToName(rider.getName());
                socketMsg.setTitle("新订单提醒");
                socketMsg.setContent("您有新的未处理订单：编号【${n}】，请及时处理。".replace("${n}", order.getOrderNum().toString()));
                socketMsg.setPcLink("/send/list?id=${id}&type=detail".replace("${id}", order.getId()));
                webSocketServer.sendMsgToUser(socketMsg);
            }
            System.out.println("============================================");
            System.out.println("订单号：" + order.getOrderCode());
            System.out.println("今日编号：" + order.getOrderNum());
            System.out.println("订单金额：" + order.getTotalAmount());
            System.out.println("配送地址：" + order.getUserAddress());
            System.out.println("下单人ID：" + order.getUserId());
            System.out.println("下单人名称：" + order.getUserName());
            System.out.println("配送人ID：" + order.getRiderId());
            System.out.println("配送人名称：" + order.getRiderName());
            System.out.println("============================================");
        }
        orderMapper.updateById(order);


        // 通知商家有新的订单
        SocketMsg socketMsg = new SocketMsg();
        socketMsg.setType("1");
        socketMsg.setActionType("88");
        socketMsg.setTitle("新订单提醒");
        socketMsg.setContent("您有新的未处理订单：编号【${n}】，请及时点击处理。".replace("${n}", order.getOrderNum().toString()));
        socketMsg.setPcLink("/order/list?id=${id}&type=detail".replace("${id}", order.getId()));
        webSocketServer.sendMsgByRole("9", socketMsg);

        return Result.opSuccess();
    }

    @Override
    public Result changeRider(String riderId, String orderId) {
        Rider rider = riderMapper.selectById(riderId);
        if (rider == null) return Result.opError("未找到该骑手！");
        Order order = orderMapper.selectById(orderId);
        if (order == null) return Result.opError(NOT_FOUND_ARTICLE);
        order.setRiderId(riderId);
        order.setRiderMobile(rider.getMobile());
        order.setRiderName(rider.getName());
        return this.update(order);
    }

    @Override
    public Result add(Order order) {
        if (orderMapper.insert(order) == 1) {
            return Result.opSuccess();
        } else {
            return Result.opError();
        }
    }

    @Override
    public Result remove(String id) {
        if (!findOrderById(id)) return Result.opError(NOT_FOUND_ARTICLE);
        if (orderMapper.deleteById(id) == 1) {
            return Result.opSuccess();
        } else {
            return Result.opError();
        }
    }

    @Override
    public Result update(Order order) {
        if (!findOrderById(order.getId())) return Result.opError(NOT_FOUND_ARTICLE);
        if (orderMapper.updateById(order) == 1) {
            return Result.opSuccess();
        } else {
            return Result.opError();
        }
    }

    @Override
    public Result done(String id) {
        Order order = orderMapper.selectById(id);
        if (order == null) return Result.opError(NOT_FOUND_ARTICLE);
        order.setStatus("2");
        order.setDoneTime(DateTime.now().toLocalDateTime());

        // 完成订单后提醒用户
        SocketMsg socketMsg = new SocketMsg();
        socketMsg.setToId(order.getUserId());
        socketMsg.setType("1");
        socketMsg.setActionType("66");
        socketMsg.setTitle("订单完成提醒");
        socketMsg.setContent("您的订单已完成，祝您用餐愉快。");
        webSocketServer.sendMsgToUser(socketMsg);

        return this.update(order);
    }

    /**
     * 用户取消订单
     */
    @Override
    public Result userCancel(String orderId, String token) {
        User user = UserServiceImpl.getUserInfoByToken(token, userMapper);
        Order order = orderMapper.selectById(orderId);
        if (order == null) return Result.opError(NOT_FOUND_ARTICLE);
        if (!order.getUserId().equals(user.getId()))
            return Result.opError("您无权操作该订单！");
        if ("1".equals(order.getIscancel()))
            return Result.opError("该订单已经申请过了，请耐心等待商家处理！");
        // 设置申请状态
        order.setIscancel("1");

        // 取消订单后提醒商家
        SocketMsg socketMsg = new SocketMsg();
        socketMsg.setType("1");
        socketMsg.setTitle("订单取消提醒");
        socketMsg.setActionType("91");
        socketMsg.setContent("有客户申请取消订单：编号【${n}】，请及时查看。".replace("${n}", order.getOrderNum().toString()));
        socketMsg.setPcLink("/order/list?id=${id}&type=detail".replace("${id}", order.getId()));
        webSocketServer.sendMsgByRole("9", socketMsg);
        webSocketServer.sendMsgToUser(socketMsg);
        return this.update(order);
    }

    /**
     * 商家取消订单
     */
    @Override
    public Result cancel(String id, String text) {
        Order order = orderMapper.selectById(id);
        if (order == null) return Result.opError(NOT_FOUND_ARTICLE);
        order.setStatus("3");

        // 取消订单后提醒用户
        SocketMsg socketMsg = new SocketMsg();
        socketMsg.setToId(order.getUserId());
        socketMsg.setType("1");
        socketMsg.setTitle("订单取消提醒");
        socketMsg.setActionType("90");
        socketMsg.setContent("您的订单已被取消，取消原因：" + text);
        webSocketServer.sendMsgToUser(socketMsg);

        return this.update(order);
    }

    @Override
    public Result selectById(String id) {
        Order order = orderMapper.selectById(id);
        if (order == null) return Result.error(NOT_FOUND_ARTICLE);
        OrderVo orderVo = OrderVo.voFromDao(order);
        Address userAddres = addressMapper.selectById(orderVo.getUserAddress());
        orderVo.setUserAddress(userAddres.getAddress() + " " + userAddres.getAddressDetail());
        // 查询该订单的所有订单商品数据
        List<OrderProduct> orderProductList = orderProductMapper.selectList(new QueryWrapper<OrderProduct>().eq("order_id", id));
        List<ProductVo> productVoList = new ArrayList<>();
        // 根据订单商品查询出商品的详细信息
        for (OrderProduct op : orderProductList) {
            Product product = productMapper.selectById(op.getProductId());
            productVoList.add(ProductVo.voFromOPDao(product, op));
        }
        orderVo.setProductList((ArrayList<ProductVo>) productVoList);
        return Result.success(orderVo);
    }

    @Override
    public Result selectPageList(OrderPageDto orderDto) {
        if (!PResult.checkPageQuery(orderDto.getPage(), orderDto.getSize())) return Result.error("分页参数错误");

        Page<Order> daoPage = new Page<>(orderDto.getPage(), orderDto.getSize());
        QueryWrapper<Order> wrapper = new QueryWrapper<Order>();
        wrapper.orderByDesc("create_time");
        if (StringUtils.isNotBlank(orderDto.getOrderCode())) {
            wrapper.like("order_code", orderDto.getOrderCode());
        }
        if (StringUtils.isNotBlank(orderDto.getUserId())) {
            wrapper.eq("user_id", orderDto.getUserId());
        }
        if (StringUtils.isNotBlank(orderDto.getUserName())) {
            wrapper.like("user_name", orderDto.getUserName());
        }
        if (StringUtils.isNotBlank(orderDto.getUserMobile())) {
            wrapper.eq("user_mobile", orderDto.getUserMobile());
        }
        if (StringUtils.isNotBlank(orderDto.getPaymode())) {
            wrapper.eq("paymode", orderDto.getPaymode());
        }
        if (StringUtils.isNotBlank(orderDto.getSendmode())) {
            wrapper.eq("sendmode", orderDto.getSendmode());
        }
        if (StringUtils.isNotBlank(orderDto.getStatus())) {
            wrapper.eq("status", orderDto.getStatus());
        }
        if (StringUtils.isNotBlank(orderDto.getIspaid())) {
            wrapper.eq("ispaid", orderDto.getIspaid());
        }
        IPage<Order> orderDaoIPage = orderMapper.selectPage(daoPage, wrapper);
        PResult rs = new PResult(orderDaoIPage);
        return Result.success(rs);
    }

    /**
     * 根据Id查询文章是否存在
     */
    public Boolean findOrderById(String id) {
        Order order = orderMapper.selectById(id);
        return order != null;
    }


    /**
     * 查询订单应该分给哪个骑手
     */
    public Rider findNextRider() {
        // 将可以派单的骑手排序，最上面的优先派单
        List<Map<String, Object>> list = riderMapper.selectOrderCount();
        System.out.println(list);
        if (list.size() != 0) {
            return riderMapper.selectById((Serializable) list.get(0).get("rider_id"));
        } else {
            return null;
        }
    }
}
